package com.idconfirmsystem.util;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import android.util.Log;

import com.idconfirmsystem.model.QueryRet;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import com.thoughtworks.xstream.converters.basic.DoubleConverter;
import com.thoughtworks.xstream.converters.basic.FloatConverter;
import com.thoughtworks.xstream.converters.basic.IntConverter;
import com.thoughtworks.xstream.converters.basic.LongConverter;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * xml解析工具类
 * 
 * 
 */

public class XmlUtils {

	private final static String TAG = XmlUtils.class.getSimpleName();
	private final static String totalnumXpath = "/Envelope/Body/result";// 返回记录个数
	private final static String showtypeXpath = "/Envelope/Body/business/result";// 显示类型
	private final static String retrieveXpath = "/Envelope/Body/business/resultset[@name='retrieve']";// 结果集合

	/**
	 * T是list泛型的封装类，比如要解析用户的任务，需要定义TaskList对象，该对象里面包含list<task>字段。
	 * 同时TaskList类增加注解
	 * ：@XStreamAlias("resultset"),其字段list<task>增加注解：@XStreamImplicit。
	 * Task类增加注解：@XStreamAlias("row")。解析后返回QueryRet<TaskList>对象 2015-8-30
	 * 
	 * @param type
	 * @param t
	 * @return
	 * @throws DocumentException
	 */
	public static <T> QueryRet<T> toBean(Class<T> type, String t) throws DocumentException {
		QueryRet<T> obj = new QueryRet<T>();
		// 干掉转义字符
		t = t.replace("&lt;", "<");
		t = t.replace("&gt;", ">");
		// 干掉头部和尾部无关xml内容
		int bgindx = t.indexOf("<?xml");
		int endIndex = t.lastIndexOf("</ns:return>");
		t = t.substring(bgindx, endIndex);
		// 干掉命名空间
		t = t.replace("soap:", "");
		t = t.replace("out:", "");
		// 初始化dom4j解析
		SAXReader saxReader = new SAXReader();
		Document document = DocumentHelper.parseText(t);
		// 获取totalnum
		try {
			Element totalNumNode = (Element) document.selectSingleNode(totalnumXpath);
			String total = totalNumNode.attributeValue("totalnum");
			obj.setTotalnum(Integer.parseInt(total));
		} catch (Exception e) {
			// TODO: handle exception
		}
		// 获取showType
		try {
			Element showt = (Element) document.selectSingleNode(showtypeXpath);
			String st = showt.attributeValue("showtype");
			obj.setShowtype(Integer.parseInt(st));
		} catch (Exception e) {
			// TODO: handle exception
		}
		// xstream获取resultset
		Node rNode = document.selectSingleNode(retrieveXpath);
		String xml = rNode.asXML();
		XStream xStream = new XStream(new DomDriver());
		xStream.ignoreUnknownElements();
		xStream.processAnnotations(type);
		T nodelist = null;
		try {
			nodelist = (T) xStream.fromXML(xml);
		} catch (Exception e) {
			// TODO: handle exception
			Log.d("xmlUtils", e.getMessage());
		}
		obj.setResult(nodelist);
		return obj;
	}

	/**
	 * 将一个xml流转换为bean实体类
	 * 
	 * @param type
	 * @param instance
	 * @return
	 * @throws AppException
	 */
	@SuppressWarnings("unchecked")
	public static <T> T toBean(Class<T> type, InputStream is) {
		XStream xmStream = new XStream(new DomDriver("UTF-8"));
		// 设置可忽略为在javabean类中定义的界面属性
		xmStream.ignoreUnknownElements();
		xmStream.registerConverter(new MyIntCoverter());
		xmStream.registerConverter(new MyLongCoverter());
		xmStream.registerConverter(new MyFloatCoverter());
		xmStream.registerConverter(new MyDoubleCoverter());
		xmStream.processAnnotations(type);
		T obj = null;
		try {
			obj = (T) xmStream.fromXML(is);
		} catch (Exception e) {
			TLog.log(TAG, "解析xml发生异常：" + e.getMessage());
		} finally {
			if (null != is) {
				try {
					is.close();
				} catch (IOException e) {
					TLog.log(TAG, "关闭流出现异常：" + e.getMessage());
				}
			}
		}
		return obj;
	}

	public static <T> T toBean(Class<T> type, byte[] bytes) {
		if (bytes == null)
			return null;
		return toBean(type, new ByteArrayInputStream(bytes));
	}

	private static class MyIntCoverter extends IntConverter {

		@Override
		public Object fromString(String str) {
			int value;
			try {
				value = (Integer) super.fromString(str);
			} catch (Exception e) {
				value = 0;
			}
			return value;
		}

		@Override
		public String toString(Object obj) {
			return super.toString(obj);
		}
	}

	private static class MyLongCoverter extends LongConverter {
		@Override
		public Object fromString(String str) {
			long value;
			try {
				value = (Long) super.fromString(str);
			} catch (Exception e) {
				value = 0;
			}
			return value;
		}

		@Override
		public String toString(Object obj) {
			return super.toString(obj);
		}
	}

	private static class MyFloatCoverter extends FloatConverter {
		@Override
		public Object fromString(String str) {
			float value;
			try {
				value = (Float) super.fromString(str);
			} catch (Exception e) {
				value = 0;
			}
			return value;
		}

		@Override
		public String toString(Object obj) {
			return super.toString(obj);
		}
	}

	private static class MyDoubleCoverter extends DoubleConverter {
		@Override
		public Object fromString(String str) {
			double value;
			try {
				value = (Double) super.fromString(str);
			} catch (Exception e) {
				value = 0;
			}
			return value;
		}

		@Override
		public String toString(Object obj) {
			return super.toString(obj);
		}
	}
}
